package savelog;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.widget.Toast;

import com.dropbox.client2.DropboxAPI;
import com.dropbox.client2.DropboxAPI.Entry;
import com.dropbox.client2.exception.DropboxException;
import com.dropbox.client2.exception.DropboxIOException;
import com.dropbox.client2.exception.DropboxParseException;
import com.dropbox.client2.exception.DropboxPartialFileException;
import com.dropbox.client2.exception.DropboxServerException;
import com.dropbox.client2.exception.DropboxUnlinkedException;

/**
 * Title: Download class for CSIS 343 Final Project 
 * Description: CS 343 Final Project - Download This class will handle downloading all save files from dropbox
 * 
 * @author Erik Olson
 * @email erik.olson-5@my.uwrf.edu
 * @author Mike Harmon
 * @email michael.harmon@my.uwrf.edu
 * @author Jack Friermuth
 * @email jack.friermuth@my.uwrf.edu
 * @author Luke Vang
 * @email luke.vang@my.uwrf.edu
 * @author Casey Golla
 * @email casey.golla@my.uwrf.edu
 * @date December 4th 2012
 */
public class Download extends AsyncTask<Void, Long, Boolean> {
	private Context mContext;
	private final ProgressDialog mDialog;
	private DropboxAPI<?> mApi;
	private String mPath;

	private FileOutputStream mFos;

	private boolean mCanceled;
	private Long mFileLen;
	private String mErrorMsg;
	private String path_to_backup;
	private boolean use_covers;

	/**
	 * Alternate constructor for Download
	 * @param Context context	  :		Current state of the app
	 * @param DropboxAPI api	  :		Helper class for dropbox api functions
	 * @param String dropboxPath :		Path to your device folder in dropbox
	 * @param String path		  :		Path to the backup folder
	 * @param boolean covers	  :		boolean to determine if the user is using game covers
	 */
	public Download(Context context, DropboxAPI<?> api, String dropboxPath, String path, boolean covers) {

		// We set the context this way so we don't accidentally leak activities
		mContext = context.getApplicationContext();

		//setting provided values
		mApi = api;
		mPath = dropboxPath;
		path_to_backup = path;
		use_covers = covers;
		
		//showing a dialog so user knows what is goin on
		mDialog = new ProgressDialog(context);
		mDialog.setMessage("Downloading Save(s)");
		mDialog.show();

	}

	/**
	 * Method to perform the download on an async thread in the background
	 * @return false
	 * @Override
	 */
	protected Boolean doInBackground(Void... arg0) {
		try {
			
			//if they cancled return
			if (mCanceled) {
				return false;
			}

			// Get the metadata for a directory
			Entry dirent = mApi.metadata(mPath, 1000, null, true, null);
			
			//check that they provided a directory and that it has contents
			if (!dirent.isDir || dirent.contents == null) {
				// It's not a directory, or there's nothing in it
				mErrorMsg = "File or empty directory";
				return false;
			}
			
			//loop through each file and download it
			for (Entry e : dirent.contents) {
			    if (!e.isDeleted) {
			    	//splitting the name up
			    	String file_name = e.fileName();
			    	String name = file_name.split( "\\." )[0];
			    	String[] name_parts = name.split( "_" );
			    	String save_name = name_parts[0];
			    	String system_id = name_parts[1];
			    	
			    	//getting the system the save is for
			    	Systems system = MainActivity.data.getSystemById( Integer.parseInt( system_id ) );
			    	
			    	//checking if there is a game for the save in the db
			    	boolean game_found = MainActivity.data.gameExistsByTitle( save_name );
			    	
			    	
			    	Games game;
			    	//checking if the save has its corresponding game in the database
			    	if( false == game_found ) {
			    		//determining what to do for game cover
			    		String game_cover = "";
			    		
						if( true == use_covers ) {
							game_cover = system.getSys_directory();
						}
						
			    		game = MainActivity.data.creategame( save_name, game_cover, 0, system.getSys_id() );
			    	} else {
			    		//game is in the database already so grab it
			    		game = MainActivity.data.getGameByTitle( save_name );
			    	}
			    	
			    	//inserting save
			    	//getting the current date
					Date date = new Date();
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd k:m:s:S");
					
			    	Saves save = MainActivity.data.createSave( game.getGame_id(), "Save added on" + sdf.format(date), sdf.format(date), sdf.format(date), "" , 0 );
			    	
			    	//updating correct path
			    	String path_to_backup_file =  path_to_backup + "/" + system.getSys_name() + "_BACKUP/" + game.getGame_title() + "_" + system.getSys_id() + "_" + save.getSave_id() + "." + system.getSys_ext();
			    	MainActivity.data.updateSaveSource( path_to_backup_file, save.getSave_id() );
			    	
			    	//reading in file
			    	File back_dat_save_up_mmmm_girl = new File( path_to_backup_file );
			    	mFos = new FileOutputStream(back_dat_save_up_mmmm_girl);
					mApi.getFile( mPath+"/"+file_name, null, mFos, null );
			    }
			}

		} catch (DropboxUnlinkedException e) {
			// The AuthSession wasn't properly authenticated or user unlinked.
		} catch (DropboxPartialFileException e) {
			// We canceled the operation
			mErrorMsg = "Download canceled";
		} catch (DropboxServerException e) {
			// Server-side exception. These are examples of what could happen,
			// but we don't do anything special with them here.
			if (e.error == DropboxServerException._304_NOT_MODIFIED) {
				// won't happen since we don't pass in revision with metadata
			} else if (e.error == DropboxServerException._401_UNAUTHORIZED) {
				// Unauthorized, so we should unlink them. You may want to
				// automatically log the user out in this case.
			} else if (e.error == DropboxServerException._403_FORBIDDEN) {
				// Not allowed to access this
			} else if (e.error == DropboxServerException._404_NOT_FOUND) {
				// path not found (or if it was the thumbnail, can't be
				// thumbnailed)
			} else if (e.error == DropboxServerException._406_NOT_ACCEPTABLE) {
				// too many entries to return
			} else if (e.error == DropboxServerException._415_UNSUPPORTED_MEDIA) {
				// can't be thumbnailed
			} else if (e.error == DropboxServerException._507_INSUFFICIENT_STORAGE) {
				// user is over quota
			} else {
				// Something else
			}
			// This gets the Dropbox error, translated into the user's language
			mErrorMsg = e.body.userError;
			if (mErrorMsg == null) {
				mErrorMsg = e.body.error;
			}
		} catch (DropboxIOException e) {
			// Happens all the time, probably want to retry automatically.
			mErrorMsg = "Network error.  Try again.";
		} catch (DropboxParseException e) {
			// Probably due to Dropbox server restarting, should retry
			mErrorMsg = "Dropbox error.  Try again.";
		} catch (DropboxException e) {
			// Unknown error
			mErrorMsg = "Unknown error.  Try again.";
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}
		return false;
	}

	/**
	 * Method to update the progress bar
	 * @Override
	 */
	protected void onProgressUpdate(Long... progress) {
		int percent = (int) (100.0 * (double) progress[0] / mFileLen + 0.5);
		mDialog.setProgress(percent);
	}

	/**
	 * Method to display a success or error message once the upload is done
	 * @Override
	 */
	protected void onPostExecute(Boolean result) {
		mDialog.dismiss();
		if (!result) {
			// Couldn't download it, so show an error
			showToast(mErrorMsg);
		}
	}

	/**
	 * Method to display a toast
	 * @param String msg :		message to be displayed
	 */
	private void showToast(String msg) {
		Toast error = Toast.makeText(mContext, msg, Toast.LENGTH_LONG);
		error.show();
	}

}
